package com.zhentao.controller;

import cn.xfyun.api.TtsClient;
import cn.xfyun.model.response.TtsResponse;
import cn.xfyun.service.tts.AbstractTtsWebSocketListener;
import com.zhentao.config.PropertiesConfig;
import okhttp3.Response;
import okhttp3.WebSocket;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;

@RestController
@RequestMapping("/api/tts")
@CrossOrigin(origins = "*")
public class TtsController {

    private static final String appId = PropertiesConfig.getAppId();
    private static final String apiKey = PropertiesConfig.getApiKey();
    private static final String apiSecret = PropertiesConfig.getApiSecret();
    private static final String OUTPUT_DIR = "D:/img/image/";

    @PostMapping("/convert")
    public ResponseEntity<?> convertTextToSpeech(@RequestBody Map<String, Object> request) {
        String text = (String) request.get("text");
        // 从请求体中获取要转换的文本
        String voiceName = (String) request.get("voiceName"); // 新增参数，默认为null
        Integer speed = (Integer) request.get("speed");
        Integer volume = (Integer) request.get("volume");
        Integer pitch = (Integer) request.get("pitch");
        // 从请求体中获取要使用的发言人声音名称，若未提供则为 null
        if (text == null || text.isEmpty()) {
            // 检查要转换的文本是否为空
            Map<String, String> response = new HashMap<>();
            // 创建一个用于存储响应信息的哈希映射
            response.put("error", "Text cannot be empty");
            // 向映射中添加错误信息
            return ResponseEntity.badRequest().body(response);
            // 返回一个 HTTP 400 错误响应，并将错误信息作为响应体
        }

        try {

            String filename = "tts_" + UUID.randomUUID().toString() + ".mp3";
            File outputFile = new File(OUTPUT_DIR + filename);
            outputFile.getParentFile().mkdirs();
            // 确保音频文件的父目录存在，如果不存在则创建
            CompletableFuture<byte[]> future = new CompletableFuture<>();
            // 创建一个 CompletableFuture 对象，用于异步处理文本转语音的结果

            TtsClient ttsClient = new TtsClient.Builder()
                    .signature(appId, apiKey, apiSecret)
                    .vcn(voiceName) // 设置发言人声音
                    .speed(speed)
                    .volume(volume)
                    .pitch(pitch)
                    .build();

            ttsClient.send(text, new AbstractTtsWebSocketListener(outputFile) {
                @Override
                public void onSuccess(byte[] bytes) {
                    future.complete(bytes);
                }

                @Override
                public void onFail(WebSocket webSocket, Throwable throwable, Response response) {
                    future.completeExceptionally(throwable);
                }

                @Override
                public void onBusinessFail(WebSocket webSocket, TtsResponse ttsResponse) {
                    future.completeExceptionally(new RuntimeException(ttsResponse.toString()));
                }
            });

            future.get();
            // 阻塞当前线程，直到 CompletableFuture 完成
            Map<String, String> response = new HashMap<>();
            // 创建一个用于存储响应信息的哈希映射
            response.put("audioFile", filename);
            // 向映射中添加生成的音频文件名
            return ResponseEntity.ok(response);
            // 返回一个 HTTP 200 成功响应，并将包含音频文件名的映射作为响应体

        } catch (Exception e) {
            // 捕获可能出现的异常
            Map<String, String> response = new HashMap<>();
            // 创建一个用于存储响应信息的哈希映射
            response.put("error", e.getMessage());
            // 向映射中添加异常信息
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(response);
            // 返回一个 HTTP 500 内部服务器错误响应，并将异常信息作为响应体
        }
    }

    @GetMapping("/audio/{filename}")
    public ResponseEntity<byte[]> getAudioFile(@PathVariable String filename) {
        try {
            File file = new File(OUTPUT_DIR + filename);
            // 创建一个 File 对象，指向指定文件名的音频文件
            if (!file.exists()) {
                // 检查文件是否存在
                return ResponseEntity.notFound().build();
                // 如果文件不存在，返回一个 HTTP 404 未找到响应
            }

            byte[] audioBytes = Files.readAllBytes(file.toPath());
            // 读取文件的所有字节到一个字节数组中

            HttpHeaders headers = new HttpHeaders();
            // 创建一个用于存储 HTTP 头部信息的对象
            headers.setContentType(MediaType.parseMediaType("audio/mpeg"));
            // 设置响应的媒体类型为音频文件
            headers.setContentLength(audioBytes.length);
            // 设置响应体的长度

            return new ResponseEntity<>(audioBytes, headers, HttpStatus.OK);
            // 返回一个 HTTP 200 成功响应，并将音频字节数组和头部信息作为响应体和头部

        } catch (IOException e) {
            // 捕获可能出现的输入输出异常
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
            // 返回一个 HTTP 500 内部服务器错误响应
        }
    }
}